﻿using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT809.Protocol.Enums;
using JT809.Protocol.Extensions;
using JTT809_2011_Service.JT809;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JTT809_2011_Service.DotNettyHandle
{
    /// <summary>
    /// JT809主链路客户端连接处理器
    /// </summary>
    public class JT809MainClientConnectionHandler : ChannelHandlerAdapter
    {
        private int total = 0;

        private readonly ILogger<JT809MainClientConnectionHandler> _logger;
        private readonly JT809MainClient _JT809MainClient;
        public JT809MainClientConnectionHandler(ILoggerFactory loggerFactory, JT809MainClient jT809MainClient)// JT809MainClient jT809MainClient
        {
            _logger = loggerFactory.CreateLogger<JT809MainClientConnectionHandler>();
            _JT809MainClient = jT809MainClient;
        }
        /// <summary>
        /// 通道激活
        /// </summary>
        /// <param name="context"></param>
        public override void ChannelActive(IChannelHandlerContext context)
        {
            string channelId = context.Channel.Id.AsShortText();
            if (_logger.IsEnabled(LogLevel.Debug))
                _logger.LogDebug($"<<<{ channelId } Successful client connection to server.");
            base.ChannelActive(context);
        }
        /// <summary>
        /// 客户端主动断开
        /// </summary>
        /// <param name="context"></param>
        public override void ChannelInactive(IChannelHandlerContext context)
        {
            string channelId = context.Channel.Id.AsShortText();
            if (_logger.IsEnabled(LogLevel.Debug))
                _logger.LogDebug($">>>{ channelId } The client disconnects from the server.");
            //Reconnect(context);
            base.ChannelInactive(context);
        }
        /// <summary>
        /// 服务器主动断开
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task CloseAsync(IChannelHandlerContext context)
        {
            string channelId = context.Channel.Id.AsShortText();
            if (_logger.IsEnabled(LogLevel.Debug))
                _logger.LogDebug($"<<<{ channelId } The server disconnects from the client.");
            //Reconnect(context).Wait();
            return base.CloseAsync(context);
        }

        public override void ChannelReadComplete(IChannelHandlerContext context)
        {
            context.Flush();
        }
        /// <summary>
        /// 超时策略
        /// </summary>
        /// <param name="context"></param>
        /// <param name="evt"></param>
        public override void UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            IdleStateEvent idleStateEvent = evt as IdleStateEvent;
            if (idleStateEvent != null)
            {
                if (idleStateEvent.State == IdleState.WriterIdle)
                {
                    string channelId = context.Channel.Id.AsShortText();
                    _logger.LogInformation($"{idleStateEvent.State.ToString()}>>>Heartbeat-{channelId}");
                    //发送主链路保持请求数据包
                    var package = JT809BusinessType.主链路连接保持请求消息.Create();
                    JT809Response jT809Response = new JT809Response(package, 1024);
                    context.WriteAndFlushAsync(jT809Response);
                }
            }
            base.UserEventTriggered(context, evt);
        }
        /// <summary>
        /// 异常
        /// </summary>
        /// <param name="context"></param>
        /// <param name="exception"></param>
        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            string channelId = context.Channel.Id.AsShortText();
            _logger.LogError(exception, $"{channelId} {exception.Message}");
            Reconnect(context);
            context.CloseAsync();
        }

        public void Reconnect(IChannelHandlerContext context)
        {
            Interlocked.Increment(ref total);
            _logger.LogDebug($"重连 total:{total}");
            //new Action(async () =>
            //{
                 _JT809MainClient.ConnectToServer().Wait();
            //}).BeginInvoke(null, null);
            //Interlocked.Increment(ref total);
            //_logger.LogDebug($"重连 total:{total}");
            //if (total == 1)
            //{
            //    new Action(async () =>
            //    {
            //        await _JT809MainClient.ConnectToServer();
            //    }).BeginInvoke(null, null);
            //}
        }
    }
}
